#include <func.h>

int main()
{
    //创建服务器的监听套接字
    int listenfd = socket(AF_INET, SOCK_STREAM, 0);
    ERROR_CHECK(listenfd, -1, "socket");

    //设置套接字的网络地址可以重用
    int on = 1;
    int ret = setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
    ERROR_CHECK(ret, -1, "setsockopt");

    struct sockaddr_in serveraddr;
    memset(&serveraddr, 0, sizeof(serveraddr));
    //指定使用的是IPv4的地址类型 AF_INET
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_port = htons(8080);
    serveraddr.sin_addr.s_addr = inet_addr("192.168.30.129");

    //以人类可阅读的方式打印网络地址
    printf("%s:%d\n", 
           inet_ntoa(serveraddr.sin_addr),
           ntohs(serveraddr.sin_port));

    //绑定服务器的网络地址
    ret = bind(listenfd, (const struct sockaddr*)&serveraddr, 
                   sizeof(serveraddr));
    ERROR_CHECK(ret, -1, "bind");

    //监听客户端的到来
    ret = listen(listenfd, 1);

    while(1) {
        //获取与对端进行交互的文件描述符
        int peerfd = accept(listenfd, NULL, NULL);
        char buff[40960] = {0};
        //接收请求数据
        int ret = recv(peerfd, buff, sizeof(buff), 0);
        printf("\nrecv %d bytes.\n", ret);
        printf("%s\n", buff);

        //发送响应数据
        char response[4096] = {0};
        const char * startLine = "HTTP/1.1 200 OK\r\n";
        const char * headers = "Server: MyHttpServer1.0\r\n"
            "Connection: keep-alive\r\n"
            "Content-Type: image/jpeg\r\n"
            "Content-Length:";// 指的是消息体的长度
        const char * emptyLine = "\r\n";
        //读取本地的图片文件
        int fd = open("image.jpg", O_RDONLY);
        ERROR_CHECK(fd, -1, "open");
        //获取图片的大小
        struct stat st;
        memset(&st, 0, sizeof(st));
        fstat(fd, &st);
        printf("file size: %ld\n", st.st_size);
        //获取图片的内容
        char * pbuff = (char*)calloc(1, st.st_size);
        read(fd, pbuff, st.st_size);
        //strlen(pbuff); //strlen函数是以 '\0' 作为结尾 

        sprintf(response, "%s%s%ld\r\n%s",
                startLine,
                headers,
                st.st_size,
                emptyLine);
        //response中没有携带消息体
        ret = send(peerfd, response, strlen(response), 0);
        printf("1 ret: %d bytes.\n", ret);
        //由于图片是二进制数据，不能将其当成字符串处理;
        //否则长度会出现问题
        //pbuff代表的是消息体
        //确保st.st_size的长度的数据要发送完毕
        int total = 0;
        ret = 0;
        while(total < st.st_size) {
            ret = send(peerfd, pbuff + total, st.st_size - total, 0);
            total += ret;
        }
        printf("2 ret: %d bytes.\n", ret);

        free(pbuff);
        close(fd);
    }

    close(listenfd);

    return 0;
};

